/** 对接mqtt协议，获取病床和病房状态 */
import { ref } from "vue"
import { defineStore } from "pinia"
import store from "@/store"
import { buildUUID } from "@/utils/index"
import { type IMqttQuickData } from "@/api/infusion/types/index"

export interface MqResult<T> {
  company: string
  device_name: string
  // 主题路径 （重要-用于判断是哪条协议）
  topic: string
  // 具体的数据 （重要-用于页面交互）
  data: T
}

export interface IDeviceOffline {
  /** 时间戳 */
  timestamp: string
  /** 离线数量 */
  num: number
}

enum SUBSCRIBETYPE {
  /** 快速匹配 */
  QUICK = "lot/web/get/alarm",
  /** 离线设备 */
  OFFLINE = "lot/web/get/receiver/network"
}

// 随机生成一个clientId格式： 'pc-17位数'
function getClientId(): string {
  const uuid = buildUUID().slice(-14)
  return `pc-${uuid}`
}

export const useMqttStore = defineStore("mqtt", () => {
  const client = ref(null)
  const msg = ref(null)
  const offDevicesCounts = ref(0) // 离线设备数量
  const quickTableData = ref<IMqttQuickData[]>([]) // 快速匹配数量表格数据

  const setOffDevicesCounts = (counts: number) => {
    offDevicesCounts.value = counts || 0
  }

  // 获取离线设备
  const getAllOffDevices = async (data: IDeviceOffline) => {
    setOffDevicesCounts(data.num)
  }

  // 处理mqtt返回值
  const checkoutResponse = (msg: Nullable<MqResult<any>>) => {
    if (!msg) return
    const { topic, data } = msg
    switch (topic) {
      case SUBSCRIBETYPE.OFFLINE:
        getAllOffDevices(data as IDeviceOffline)
        break

      case SUBSCRIBETYPE.QUICK:
        arrangeQuickData(data as IMqttQuickData[])
        break
      default:
        break
    }
  }

  // 处理快速匹配表格数据
  const arrangeQuickData = (data: IMqttQuickData[]) => {
    data.forEach((item) => {
      quickTableData.value.push({
        ...item,
        device_name: item.sort.toString() + "号设备"
      })
      console.info(item)
    })

    // 去重
    const map = new Map()
    quickTableData.value.forEach((item) => {
      map.set(item.device_code, item)
    })

    quickTableData.value = Array.from(map.values()).sort((a, b) => a.sort - b.sort)
  }

  // 重置数据并取消订阅
  const resetQuickData = () => {
    quickTableData.value = []
    ;(client.value as any).unsubscribe(SUBSCRIBETYPE.QUICK, {})
  }

  const mqConnect = () => {
    if (client.value) return
    const host = import.meta.env.DEV ? import.meta.env.VITE_GLOB_HOSTNAME : location.hostname
    const port = 18083
    const clientId = getClientId()

    const Paho = (window as any).Paho
    client.value = new Paho.Client(host, port, clientId) // connect the client
    ;(client.value as any).connect({
      timeout: 4000, // 连接超时时间/秒
      keepAliveInterval: 20, // 1800秒内没有活动自动断开连接 默认值为60秒 心跳
      cleanSession: true, // 如果为true(默认值)，则在成功连接时删除客户端和服务器持久化状态
      useSSL: false, // 如果存在且为true，则使用SSL Websocket连接
      invocationContext: {}, // 传递给onSuccess回调或onFailure回调

      reconnect: true, // 设置如果连接丢失，客户端是否自动尝试重新连接到服务器 如果设置为false，当连接丢失时，客户端将不会尝试自动重新连接到服务器。  如果设置为true，当连接丢失时，客户端将尝试重新连接服务器。 在尝试重新连接之前，它最初将等待1秒，对于每一次失败的重新连接尝试，延迟将加倍，直到达到2分钟，此时延迟将保持在2分钟。
      userName: "test",
      password: "123456",

      onSuccess: () => {
        console.info("连接成功")
        // 连接mqtt成功后，订阅web端的离线设备数据通知
        ;(client.value as any).subscribe(SUBSCRIBETYPE.OFFLINE, {
          qos: 2
        })
      },
      // 连接失败
      onFailure: (err: any) => {
        console.warn("Mqtt connection fail", err)
      }
    }) // called when the client loses its connection
    ;(client.value as any).onConnectionLost = (responseObject: any) => {
      if (responseObject.errorCode !== 0) {
        console.log("onConnectionLost:" + responseObject.errorMessage)
      }
    }
    // called when a message arrives
    ;(client.value as any).onMessageArrived = (message: any) => {
      msg.value = {
        topic: message.topic,
        ...JSON.parse(message.payloadString)
      }

      checkoutResponse(msg.value)
    }
  }

  // 订阅快速匹配
  const subscribe = (deviceSubscribeUrl: string) => {
    ;(client.value as any).subscribe(deviceSubscribeUrl, {
      qos: 2
    })
  }

  const close = () => {
    client.value && (client.value as any).disconnect()
    client.value = null
  }

  return {
    client,
    msg,
    offDevicesCounts,
    quickTableData,
    resetQuickData,
    subscribe,
    close,
    mqConnect,
    checkoutResponse,
    setOffDevicesCounts
  }
})

/** 在 setup 外使用 */
export function useMqttStoreHook() {
  return useMqttStore(store)
}
